package com.chenxin.wms.process.inbound.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chenxin.common.annotation.WmsLogs;
import com.chenxin.common.core.domain.ProcResult;
import com.chenxin.common.enums.wms.*;
import com.chenxin.common.utils.StringUtils;
import com.chenxin.wms.domain.*;
import com.chenxin.wms.domain.dto.WipMaterialReleaseParams;
import com.chenxin.wms.mapper.LocationMapper;
import com.chenxin.wms.mapper.StockMapper;
import com.chenxin.wms.mapper.TaskMapper;
import com.chenxin.wms.mapper.ZoneMapper;
import com.chenxin.wms.process.inbound.IContNoReleaseProcess;
import com.chenxin.wms.process.task.IWcsTaskProcess;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;


/**
 * 入库放行处理实现类
 */
@Service
public class ContNoReleaseImpl implements IContNoReleaseProcess {

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private LocationMapper locationMapper;
    @Autowired
    private ZoneMapper zoneMapper;

    @Autowired
    private StockMapper stockMapper;

    @Autowired
    private IWcsTaskProcess wcsTaskProcess;

    @Transactional
    @WmsLogs(name = "入库放行处理")
    @Override
    public ProcResult call(WipMaterialReleaseParams dto) {
        // 1. 参数校验
        if (dto == null) {
            return ProcResult.error("wip_release_001", "请求参数不能为空");
        }

        String contNo = dto.getContNo();
        if (StringUtils.isEmpty(contNo)) {
            return ProcResult.error("wip_release_000", "托盘号不能为空");
        }
        Long creator = dto.getCreator();
        Date workDate = new Date();

        // 2. 根据托盘号查找所有相关的上架任务
        QueryWrapper<TaskEntity> taskQW = new QueryWrapper<>();
        taskQW.lambda()
                .eq(TaskEntity::getFromContNo, contNo)
                .eq(TaskEntity::getTaskType, TaskType.RECEIVE_IN.getCode())
                .le(TaskEntity::getTaskStatus, TaskStatus.INIT.getCode());

        List<TaskEntity> releaseTasks = taskMapper.selectList(taskQW);
        if (releaseTasks == null || releaseTasks.size() == 0) {
            return ProcResult.error("wip_release_003", "托盘【" + contNo + "】未找到可放行任务！");
        }
        // 判断是否存在起始位置不同的任务
        long count = releaseTasks.stream().map(TaskEntity::getFromPosition).distinct().count();
        if (count > 1) {
            return ProcResult.error("wip_release_002", "托盘【" + contNo + "】存在起始位置不同的任务，请确认！");
        }

        // 3.根据托盘号查询所有库存信息，检查是否都是合格品
        QueryWrapper<StockEntity> stockQW = new QueryWrapper<>();
        stockQW.lambda().eq(StockEntity::getContNo, contNo);
        List<StockEntity> releaseStocks = stockMapper.selectList(stockQW);
        if (releaseStocks == null || releaseStocks.size() == 0) {
            return ProcResult.error("wip_release_004", "托盘【" + contNo + "】对应的库存信息不存在，无法放行");
        }

        // 检查所有库存是否都是合格品（需SAP质检合格后放行入库）
        for (StockEntity stock : releaseStocks) {
            if (!StockQuality.QB.getCode().equals(stock.getQualityStatus())) {
                return ProcResult.error("wip_release_005", "托盘【" + contNo + "】中存在【不合格】库存，无法放行");
            }
        }

        // 根据起始位置判断放行库区（匹配合适的上架货位）
        TaskEntity releaseTask = releaseTasks.get(0);
        String fromPosition = releaseTask.getFromPosition();

        QueryWrapper<LocationEntity> locationQW = new QueryWrapper<>();
        locationQW.lambda().eq(LocationEntity::getLocationNo, fromPosition).last("limit 1");
        LocationEntity fromLocation = locationMapper.selectOne(locationQW);
        if (fromLocation == null) {
            return ProcResult.error("wip_release_008", "托盘【" + contNo + "】的起始位置【" + fromPosition + "】未在货位表维护");
        }
        // 起始位置的库区ID
        Long zoneId = fromLocation.getZoneId();
        // 起始位置的设备编号
        String dvcNo = fromLocation.getDvcNo();
        // 获取库区相关信息
        ZoneEntity releaseZone = zoneMapper.selectById(zoneId);
        if (releaseZone == null) {
            return ProcResult.error("wip_release_007", "托盘【" + contNo + "】的起始位置【" + fromPosition + "】对应的库区ID【" + zoneId + "】不存在");
        }
        String zoneType = releaseZone.getZoneType();
        // 按需求匹配空闲可用的货位
        QueryWrapper<LocationEntity> toPositionQW = new QueryWrapper<>();
        toPositionQW.lambda()
                .eq(LocationEntity::getZoneId, zoneId)
                .eq(LocationEntity::getLocationType, LocationType.HW.getCode())
                .eq(LocationEntity::getLocationVr, 1)
                .eq(LocationEntity::getLocationStatus, LocationStatus.IDLE.getCode())
                .eq(LocationEntity::getIsActive, LocationStatus.USABLE.getCode())
                .last("order by level_num,column_num,row_num limit 1");
        LocationEntity toLocation = locationMapper.selectOne(toPositionQW);
        if (toLocation == null) {
            return ProcResult.error("wip_release_006", "托盘【" + contNo + "】放行失败，库区【" + zoneId + "】暂无可用的空闲货位！");
        }
        String toPosition = toLocation.getLocationNo();
        // 锁定可用位置信息
        toLocation.setContNo(contNo);
        toLocation.setLocationStatus(LocationStatus.PRE.getCode());
        toLocation.setUpdater(creator);
        toLocation.setUpdateDate(workDate);
        toLocation.setComments("托盘【" + contNo + "】放行，已预约该货位");
        locationMapper.updateById(toLocation);

        // 更新任务信息
        for (TaskEntity task : releaseTasks) {
            task.setToPosition(toPosition);
            task.setTaskStatus(TaskStatus.EXEC.getCode());
            task.setComments("托盘【" + contNo + "】放行成功");
            task.setUpdater(creator);
            task.setUpdateDate(workDate);
            taskMapper.updateById(task);
        }

        // 根据放行区域判断是否需要生成对应设备的搬送任务
        if (ZoneType.AUTO.getCode().equals(zoneType)) {
            // 暂以时间戳作为requestPk
            WcsTaskEntity wcsTask = new WcsTaskEntity();
            wcsTask.setRequestPk(String.valueOf(System.currentTimeMillis()));
            wcsTask.setDvcNo(dvcNo);
            wcsTask.setContNo(contNo);
            wcsTask.setTrkType(TaskType.WCS_IN.getCode());
            wcsTask.setFrmPos(fromPosition);
            wcsTask.setToPos(toPosition);
            wcsTask.setCurPos(fromPosition);
            wcsTask.setTrkStatus(TaskStatus.INIT.getCode());
            wcsTask.setCreator(creator);
            wcsTask.setCreateDate(workDate);
            Long trkId = wcsTaskProcess.procWmsToWcsInsert(wcsTask);
        }

        return ProcResult.success("托盘【" + contNo + "】放行成功，目标货位【" + toPosition + "】");
    }
}